#include"ThreadCache.hpp"
#include"CentralCache.hpp"

void* ThreadCache::Allocate(size_t size)
{
    assert(size<MAX_BYTES);
    size_t alignSize=sizeclass::RoundUp(size);
    size_t index=sizeclass::Index(size);

    //哈希桶对应下标链表不为空，直接弹出，否则向下一层获取
    if(!_freelist[index].Empty())
    {
        return _freelist[index].Pop();
    }
    else
    {
        return FetchFromCentralCache(index, alignSize);
    }

};
void* ThreadCache::FetchFromCentralCache(size_t index,size_t size)
{
    //慢开始反馈调节算法
    //一种慢增长模式，使获得的内存块数目从1开始缓慢增长直到大于NumMoveSize所获得的值
    //1.最开始不会一次向central cache要太多，因为可能用不完
    //2.如果这个大小需求不够，那么会增长直到上限
    //3，size越大，向central cache要的就越小
    //4，size越小，向central cache要的就越大，但是都是从一开始给
   
    size_t batchNum=std::min(_freelist[index].MaxSize(),sizeclass::NumMoveSize(size));
    if(batchNum == _freelist[index].MaxSize())
    {
        _freelist[index].MaxSize()++;//可以自动调节想要的增长速度
    }


    void* start=nullptr;
    void* end=nullptr;
    size_t actalNum=CentralCache::GetInc()->FectRangObj(start,end,batchNum,size);
    assert(actalNum>0);

    //只有一个内存块直接返回，多个的话插入链表
    if(actalNum == 1)
    {
        assert(start == end);
        return start;
        
    }
    else
    {
        _freelist[index].PushRange(*(void**)start,end,actalNum-1);
        return start;
    }
    
}

void ThreadCache::ListToLong(FreeList& list,size_t size)
{   
    void* start;
    void* end;
    list.PopRange(start,end,list.MaxSize());
    CentralCache::GetInc()->ReleaseListToSpans(start, size);
}

void ThreadCache::Deallocate(void* ptr,size_t size)
{
    assert(ptr);
    assert(size<MAX_BYTES);
//找到对应的自由链表插入换回来的内存
    size_t index=sizeclass::Index(size);
    _freelist[index].Push(ptr);

    if(_freelist[index].size()>=_freelist[index].MaxSize())
    {
        ListToLong(_freelist[index],size);
    }
}

